/****************************************************************************
  From Qt examples
****************************************************************************/

#include "proxyThread.h"

#include <QtNetwork>
#include <iostream>
using namespace std;

ProxyThread::ProxyThread(int socketDescriptor, unsigned int sTime, double tDenomination,
                         const QString &message, QObject *parent)
    : QThread(parent), socketDescriptor(socketDescriptor), text(message)
{
    this->socketDescriptor = socketDescriptor;
    serverFirstTime = true;
    simTime = sTime; //set from the gui
    timeDenomination = tDenomination;    //set from the gui

}

void ProxyThread::run()
{
    //Thread starts here
    blockS=0;
    qDebug()<< socketDescriptor << "Starting Thread";
    socket = new QTcpSocket();
    if (!socket->setSocketDescriptor(this->socketDescriptor)) {
        emit error(socket->error());
        return;
    }
    //direct connection to the thread
    connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
    connect(socket,SIGNAL(disconnected()),this,SLOT(disconnect()),Qt::DirectConnection);

    qDebug()<< socketDescriptor << "Client Connected";

    //test
    exec();

}

void ProxyThread::readyRead()
{
   // blockS=0;
   // QByteArray Data = socket->readAll();
  //  QString myString(Data);
  //  QString temp = Data;

    qDebug() << "Original blockSize: " << blockS;

    QDataStream in(socket);
    in.setVersion(QDataStream::Qt_4_0);

    if (blockS == 0) {
        if (socket->bytesAvailable() < (int)sizeof(quint16))
            return;
        in >> blockS;
    }

    qDebug() << "BlockSize: " << blockS;

    if (socket->bytesAvailable() < blockS)
        return;

    qDebug() << "Recieved the full msg";

    QString nextMessage;
    in >> nextMessage;
    text = nextMessage;
    //qDebug() << socketDescriptor << "Data in: " << Data;
    //qDebug() << socketDescriptor << "myString in: " << myString;
    //qDebug() << socketDescriptor << "temp in: " << temp;
    qDebug() << socketDescriptor << "Message in: " << nextMessage;
    blockS = 0;


    if (text == "client") {
        // send the next available server
        emit incomingRequest(socketDescriptor);
    }
    else if (text.contains("server::")) {

        if(serverFirstTime)
        {
            emit addServer(socketDescriptor, text.section("::", 1), (void*)this->currentThreadId());

            //send(currentTime =0, timedenomiantion=1,)
            QString simData = QString::number(simTime,10) + "::" + QString::number(timeDenomination);
            sendtoServer(simData);
            serverFirstTime = false;
            return;
        }
        else if (text.contains("hardware failure")) {
            emit sendLoadToProxy(-1, socketDescriptor);
        }
        else if(text.contains("load::")) {
            qDebug() << "Unloading server status message";
            unsigned short load = text.section("::", 2, -1).toUShort();
            emit sendLoadToProxy(load,socketDescriptor);
        }

    }


    emit clientMessage(nextMessage);
    //socket->write(Data);
    //qDebug() << "Proxy Write back";
    //sendtoServer("TESTING");
}


// This function can be used to communicate with all the connected clients
// Echoes the given message to all clients connected
void ProxyThread::sendtoServer(QString info)
{
    qDebug() << "Proxy is sending information server: " << info;

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    out << (quint16)0;
    out << info;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    socket->write(block);

    qDebug() << "Proxy Thread wrote: " << info;
}

void ProxyThread::disconnect()
{
    qDebug() << socketDescriptor << "Disconnecting: ";
    emit disconnectedServer(socketDescriptor);

    socket->disconnectFromHost();
    socket->deleteLater();
    exit(0); // Thread no longer needed
}

void ProxyThread::sendTimeSync(unsigned int time)
{
    QString packet = QString::number(time);
    sendtoServer(packet);
}

void ProxyThread::serverAdded(ServerLoad* modelPointer, void* threadID)
{
    if (threadID == (void*) this->currentThreadId()) {
        qDebug() << "Found my model pointer!";
        myModel = modelPointer;
    }
}

void ProxyThread::serverAllocated(int sd, QHostAddress serverAddress, quint16 serverPort)
{
    if (socketDescriptor == sd) {
        sendtoServer(serverAddress.toString() + "::" + QString::number(serverPort));
    }
}
